//*****************************************************************************
//
//  File........: LCD_functions.c
//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  Compiler....: AVR-GCC 3.3.1; avr-libc 1.0
//
//  Description.: Additional LCD functions, scrolling text and write data
//
//  Revisions...: 1.0
//
//  YYYYMMDD - VER. - COMMENT                                       - SIGN.
//
//  20021015 - 1.0  - Created                                       - LHM
//  20030116 - 2.0  - Code adapted to AVR Butterflyup               - KS
//  20031009          port to avr-gcc/avr-libc                      - M.Thomas
//  20060128          small modification ("flash buffer") in puts_f - M.Thomas
//
//*****************************************************************************

//  Include files
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "LCD_driver.h"
#include "LCD_functions.h"
/// rrl removed  #include "BCD.h"
// mt only for KEY_* and ST_OPTIONS_DISPLAY* definitions:
///rrl - #include "main.h"
#include "button.h"


#define FALSE   0
#define TRUE    (!FALSE)

uint8_t CONTRAST = LCD_INITIAL_CONTRAST;
const uint8_t clocks[] PROGMEM = {8, 4, 2, 1};
const char hexnibble[] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};


// Start-up delay before scrolling a string over the LCD. "LCD_driver.c"
extern char gLCD_Start_Scroll_Timer;

/****************************************************************************
*
*	Function name : LCD_puts_f
*
*	Returns :		None
*
*	Parameters :	pFlashStr: Pointer to the string in flash
*                   scrollmode: Not in use
*
*	Purpose :		Writes a string stored in flash to the LCD
*
*****************************************************************************/

void LCD_puts_f(const char *pFlashStr, char scrollmode)
{
    uint8_t i;
    char c;    // local variable 20060128

    while (gLCD_Update_Required);      // Wait for access to buffer

    for (i = 0; ( c = (const char)(pgm_read_byte(&pFlashStr[i]))) && ( i < TEXTBUFFER_SIZE ); i++)
    {
        gTextBuffer[i] = c;
    }

    gTextBuffer[i] = '\0';

    if (i > 6)
    {
        gScrollMode = 1;        // Scroll if text is longer than display size
        gScroll = 0;
        gLCD_Start_Scroll_Timer = 3;    //Start-up delay before scrolling the text
    }
    else
    {
        gScrollMode = 0;        
        gScroll = 0;
    }

    gLCD_Update_Required = 1;
}




/****************************************************************************
*
*	Function name : LCD_puts
*
*	Returns :		None
*
*	Parameters :	pStr: Pointer to the string
*                   scrollmode: Not in use
*
*	Purpose :		Writes a string to the LCD
*
*****************************************************************************/
void LCD_puts(char *pStr, char scrollmode)
{
    uint8_t i; 

    while (gLCD_Update_Required);      // Wait for access to buffer

    for (i = 0; pStr[i] && i < TEXTBUFFER_SIZE; i++)
    {
        gTextBuffer[i] = pStr[i];
    }

    gTextBuffer[i] = '\0';

    if (i > 6)
    {
        gScrollMode = 1;        // Scroll if text is longer than display size
        gScroll = 0;
        gLCD_Start_Scroll_Timer = 3;    //Start-up delay before scrolling the text
    }
    else
    {
        gScrollMode = 0;        
        gScroll = 0;
    }

    gLCD_Update_Required = 1;
}




/****************************************************************************
*
*	Function name : LCD_putc
*
*	Returns :		None
*
*	Parameters :	digit: Which digit to write on the LCD
*                   character: Character to write
*
*	Purpose :		Writes a character to the LCD
*
*****************************************************************************/
void LCD_putc(uint8_t digit, char character)
{
    if (digit < TEXTBUFFER_SIZE)
        gTextBuffer[digit] = character;
}


/****************************************************************************
*
*	Function name : LCD_Clear
*
*	Returns :		None
*
*	Parameters :	None
*
*	Purpose :		Clear the LCD
*
*****************************************************************************/
void LCD_Clear(void)
{
    uint8_t i; 

    for (i=0; i<TEXTBUFFER_SIZE; i++)
        gTextBuffer[i] = ' ';
}


/****************************************************************************
*
*	Function name : LCD_Colon
*
*	Returns :		None
*
*	Parameters :	show: Enables the colon if TRUE, disable if FALSE
*
*	Purpose :		Enable/disable colons on the LCD
*
*****************************************************************************/
void LCD_Colon(char show)
{
    gColon = show;
}


/****************************************************************************
*
*	Function name : LCD_UpdateRequired
*
*	Returns :		None
*
*	Parameters :	update: TRUE/FALSE
*                   scrollmode: not in use
*
*	Purpose :		Tells the LCD that there is new data to be presented
*
*****************************************************************************/
void LCD_UpdateRequired(char update, char scrollmode)
{

    while (gLCD_Update_Required);
    
    gScrollMode = scrollmode;
    gScroll = 0;

    gLCD_Update_Required = update;
}


/****************************************************************************
*
*	Function name : LCD_FlashReset
*
*	Returns :		None
*
*	Parameters :	None
*
*	Purpose :		This function resets the blinking cycle of a flashing digit
*
*****************************************************************************/
void LCD_FlashReset(void)
{
    gFlashTimer = 0;
}



/****************************************************************************
*
*	Function name : SetContrast
*
*   Parameters :    char input
*
*	Purpose :		Adjust the LCD contrast
*
*****************************************************************************/
void SetContrast(char input)
{
    LCD_Clear();
    LCD_putc(0, 'A');
    LCD_putc(1, 'B');
    LCD_putc(2, 'C');
    LCD_putc(3, 'D');
    LCD_putc(4, 'E');
    LCD_putc(5, 'F');
    LCD_UpdateRequired(TRUE, 0);
    LCD_CONTRAST_LEVEL(input);
}


void hexstr(char *somestring, uint8_t  somebyte) {
	somestring[0] = (const char)(pgm_read_byte(&hexnibble[somebyte >> 4]));
	somestring[1] = (const char)(pgm_read_byte(&hexnibble[somebyte & 0x0F]));
    somestring[2] = 0;
}


void show1hex (uint8_t byte1) {
	LCD_putc(0, (const char)(pgm_read_byte(&hexnibble[byte1 >> 4])));
	LCD_putc(1, (const char)(pgm_read_byte(&hexnibble[byte1 & 0x0F])));
	LCD_putc(2, ' ');
	LCD_putc(3, 'h');
	LCD_putc(4, 'e');
	LCD_putc(5, 'x');
	LCD_putc(6, '\0');
	LCD_UpdateRequired(TRUE, 0);
}


void show2hex (uint8_t byte1, uint8_t byte2) {
	LCD_putc(0, (const char)(pgm_read_byte(&hexnibble[byte1 >> 4])));
	LCD_putc(1, (const char)(pgm_read_byte(&hexnibble[byte1 & 0x0F])));
	LCD_putc(2, ' ');
	LCD_putc(3, ' ');
	LCD_putc(4, (const char)(pgm_read_byte(&hexnibble[byte2 >> 4])));
	LCD_putc(5, (const char)(pgm_read_byte(&hexnibble[byte2 & 0x0F])));
	LCD_putc(6, '\0');
	LCD_UpdateRequired(TRUE, 0);
}

void show3hex (uint8_t byte1, uint8_t byte2, uint8_t byte3 ) {
	LCD_putc(0, (const char)(pgm_read_byte(&hexnibble[byte1 >> 4])));
	LCD_putc(1, (const char)(pgm_read_byte(&hexnibble[byte1 & 0x0F])));
	LCD_putc(2, (const char)(pgm_read_byte(&hexnibble[byte2 >> 4])));
	LCD_putc(3, (const char)(pgm_read_byte(&hexnibble[byte2 & 0x0F])));
	LCD_putc(4, (const char)(pgm_read_byte(&hexnibble[byte3 >> 4])));
	LCD_putc(5, (const char)(pgm_read_byte(&hexnibble[byte3 & 0x0F])));
	LCD_putc(6, '\0');
	LCD_UpdateRequired(TRUE, 0);
}


void show_mhz (void) {
	uint8_t somebyte = (const char)(pgm_read_byte(&clocks[CLKPR]));
	LCD_putc(0, (const char)(pgm_read_byte(&hexnibble[somebyte >> 4])));
	LCD_putc(1, (const char)(pgm_read_byte(&hexnibble[somebyte & 0x0F])));	
	LCD_putc(2, ' ');
	LCD_putc(3, 'M');
	LCD_putc(4, 'h');
	LCD_putc(5, 'z');
	LCD_putc(6, '\0');
	LCD_UpdateRequired(TRUE, 0);
}
